package cc.eddic.practice.spring.webapi;

import cc.eddic.practice.spring.domain.Option;
import cc.eddic.practice.spring.domain.SubCategory;
import cc.eddic.practice.spring.dto.*;
import cc.eddic.practice.spring.repository.CategoryRepository;
import cc.eddic.practice.spring.repository.QuestionRepository;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.transaction.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/questions")
public class QuestionController {
    public QuestionController(QuestionRepository repository) {
        this.repository = repository;
    }

    @PostMapping
    public HttpEntity<?> add(@RequestBody final QuestionAddRequest model) {
        val question = repository.save(model.as());
        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(question.getId()).toUri()).build();
    }

    @GetMapping("/{id}")
    public HttpEntity<QuestionResponse> get(@PathVariable("id") final long id) {
        if (log.isDebugEnabled()) log.debug("id={}", id);
        val question = repository.findById(id).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(QuestionResponse.from(question));
    }

    @Transactional
    @PostMapping("/{questionId}/options")
    public HttpEntity<?> add(@PathVariable("questionId") Long questionId, @RequestBody final OptionAddRequest model) {
        val question = repository.findById(questionId).orElseThrow(NoSuchElementException::new);
        val option = model.as();
        question.add(option);
        repository.save(question);

        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{optionId}")
                .buildAndExpand(option.getId()).toUri()).build();
    }

    @GetMapping("/{questionId}/options")
    public HttpEntity<?> get(@PathVariable("questionId") Long questionId) {
        if (log.isDebugEnabled()) log.debug("questionId ={}", questionId);
        val question = repository.findById(questionId).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(question.getOptions().stream().map(OptionResponse::from).collect(Collectors.toList()));

    }

    @GetMapping("/{questionId}/options/{optionId}")
    public HttpEntity<?> get(@PathVariable("questionId") Long categoryId, @PathVariable("optionId") Long optionId) {

        val question = repository.findById(categoryId).orElseThrow(NoSuchElementException::new);
        val option = question.getOptions().stream().filter(new Predicate<Option>() {
            @Override
            public boolean test(Option option) {
                return option.getId().equals(optionId);
            }
        }).findFirst().orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(OptionResponse.from(option));

    }


    @DeleteMapping("/{id}")
    public HttpEntity<?> del(@PathVariable("id") final long id) {
        repository.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping
    public HttpEntity<List<QuestionResponse>> getAll() {
        val questions = repository.findAll().stream().map(QuestionResponse::from).collect(Collectors.toList());
        return ResponseEntity.ok(questions);
    }


    private final QuestionRepository repository;


}
